package com.marion.jpamodel.criteria;

import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * 条件组合器
 * @author Marion
 * @date 2022/3/2 16:00
 */
public class Criteria<T> implements Specification<T> {

    private List<Criterion> criterions = new ArrayList<>();

    /**
     * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
     * {@link Root} and {@link CriteriaQuery}.
     * @param root            must not be {@literal null}.
     * @param query           must not be {@literal null}.
     * @param criteriaBuilder must not be {@literal null}.
     * @return a {@link Predicate}, may be {@literal null}.
     */
    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {

        if (!criterions.isEmpty()) {

            List<Predicate> predicates = new ArrayList<>();

            for (Criterion criterion : criterions) {
                predicates.add(criterion.toPredicate(root, query, criteriaBuilder));
            }

            if (predicates.size() > 0) {
                return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
            }
        }

        return criteriaBuilder.conjunction();
    }

    public Criteria<T> add(Criterion criteria) {
        if (criteria != null) {
            criterions.add(criteria);
        }

        return this;
    }
}
